#include "cserverManz.h"
#include <cpr/cpr.h>

#define CALLBACK_TEMPLATE(F) (std::bind(&cserverManz::F, this, std::placeholders::_1, std::placeholders::_2))
#define HTTP_SUCCESS_CODE 200
#define HTTP_ERROR_CODE 500
cserverManz::cserverManz() {
    m_poller = EventPollerPool::Instance().getPoller();
}

string cserverManz::GetUrlByKey(const string &app, const string &stream) {
    // 根据app和stream返回要注册的RTSP URL
    // __defaultVhost__/rst/3b9bdd6bb05d1e7c30522048695db04c
    if (!m_rtsp_key.empty()) {
        // 先关闭上一个回放流,
        // 判断是否一样的？
        // __defaultVhost__/34020000001110000100/20241218T102052Z20241218T141017Z
        string _tkey = str_format("__defaultVhost__/%s/%s", m_rtsp_key, stream);
        DebugL << "判断是否一样的:" << m_rtsp_key;
        if (m_rtsp_key != _tkey) {
            DebugL << "关闭上一个回放流:" << m_rtsp_key;
            OndelStreamProxy();
        }
    }
    // 查找出URL
    std::string key = generateKey(app, stream);
    std::unique_lock<std::mutex> lock(m_mutexURL);
    auto it = m_URLdataMap.find(key);
    if (it != m_URLdataMap.end()) {
        return it->second;
    }
    ErrorL << "未找到该key:" << key;
    return ""; // 如果没有找到，返回空字符串
}

void cserverManz::SetUrlByKey(const string &app, const string &stream, const string &url) {
    std::string key = generateKey(app, stream);
    std::unique_lock<std::mutex> lock(m_mutexURL);
    m_URLdataMap[key] = url;
}

void cserverManz::OnInitListener() {

    NoticeCenter::Instance().addListener(nullptr, Broadcast::kBroadcastHttpRequest, [this](BroadcastHttpRequestArgs) {
        // 封装HTTP响应函数
        auto sendResponse = [&](int statusCode, const Json::Value &responseData) {
            HttpSession::KeyValue headerOut;
            invoker(statusCode, headerOut, responseData.toStyledString());
        };

        // 封装错误响应函数
        auto sendErrorResponse = [&](const string &errorMessage) {
            HttpSession::KeyValue headerOut;
            Json::Value response;
            response["code"] = -1;
            response["msg"] = errorMessage;
            sendResponse(500, response);
        };

        string _parURL = parser.url();
        consumed = true; // 该http请求已被消费
        DebugL << "触发:" << _parURL;
        Json::Value args;
        DebugL << "Content-Type:" << parser["Content-Type"];
        if (parser["Content-Type"].find("application/json") != string::npos) {
            DebugL << "json格式的请求";
            Json::Reader reader;
            reader.parse(parser.content(), args);

        } else if (parser["Content-Type"].find("application/x-www-form-urlencoded") != string::npos) {
            DebugL << "form格式的请求";
            for (auto &pr : parser.getUrlArgs()) {
                args[pr.first] = pr.second;
            }
        } else {
            ErrorL << "未处理的Content-Type";
            sendErrorResponse("Content-Type错误");
            return;
        }
        DebugL << args.toStyledString();
        // 查找该url对应的处理函数
        auto it = m_map_api.find(_parURL);
        if (it != m_map_api.end()) {
            try {
                Json::Value _val;
                int statusCode = 200;
                statusCode = it->second(args, _val);
                sendResponse(statusCode, _val);
            } catch (const std::exception &e) {
                ErrorL << e.what();
                sendErrorResponse(e.what());
            }
        }
    });
}

bool cserverManz::OnaddStreamProxy(const string &app, const string &stream, const string sUrl) {
    InfoL << "主动拉流..." << sUrl;
    cpr::Response res = cpr::Get(
        cpr::Url { m_mediaURL, "/index/api/addStreamProxy" },
        cpr::Parameters {
            { "secret", m_mediaSecret },
            { "vhost", "__defaultVhost__" },
            { "app", app },
            { "stream", stream },
            { "url", sUrl },
        },
        cpr::Timeout(1500));

    DebugL << "URL:" << sUrl;

    if (res.status_code == 200) {
        DebugL << "返回: " << res.text;
        // 这里把Key解析出来保存起来用于主动关闭流
        const std::string rawJson = res.text;
        const auto rJsonLength = static_cast<int>(rawJson.length());

        JSONCPP_STRING err;
        Json::Value root;
        Json::CharReaderBuilder builder;
        const std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
        if (!reader->parse(rawJson.c_str(), rawJson.c_str() + rJsonLength, &root, &err)) {
            ErrorL << "OnaddStreamProxy 解析JSON失败!";
            return "";
        }
        //
        try {
            if (root.isMember("data")) {
                Json::Value _data = root["data"];
                m_rtsp_key = _data["key"].asString();
            }
        } catch (const std::exception &e) {
            ErrorL << "JSON Error";
        }
        return true;
    }

    return false;
}

bool cserverManz::OndelStreamProxy() {
    InfoL << "主动关闭流...";
    cpr::Response res = cpr::Get(
        cpr::Url { m_mediaURL, "/index/api/delStreamProxy" },
        cpr::Parameters {
            { "secret", m_mediaSecret },
            { "key", m_rtsp_key },

        },
        cpr::Timeout(1500));

    if (res.status_code == 200) {
        // DebugL << "返回: " << res.text;
        m_rtsp_key = "";
        return true;
    }
    return false;
}

string cserverManz::generateKey(const std::string &app, const std::string &stream) {
    return app + ":" + stream;
}

void cserverManz::OnInitAPIFUN() {
    m_map_api.emplace("/index/hook/on_stream_not_found", CALLBACK_TEMPLATE(HandleStreamNotFound));
    m_map_api.emplace("/api/addstream/", CALLBACK_TEMPLATE(HandleAddStream));
    m_map_api.emplace("/api/addplayback/", CALLBACK_TEMPLATE(HandleAddPlayback));
}

int cserverManz::HandleAddStream(const Json::Value &args, Json::Value &rval) {
    try {
        if (args.isMember("app")) {
            SetUrlByKey(args["app"].asString(), args["stream"].asString(), args["url"].asString());
        }
    } catch (const std::exception &e) {
        ErrorL << e.what();
        rval["code"] = -1;
        rval["msg"] = e.what();
        return HTTP_ERROR_CODE;
    }
    rval["code"] = 0;
    rval["msg"] = "success";
    rval["ip"] = m_local_ip;
    return HTTP_SUCCESS_CODE;
}

int cserverManz::HandleStreamNotFound(const Json::Value &args, Json::Value &rval) {
    // 根据json内容查找到源然后注册源
    // app
    // stream
    // url
    weak_ptr<cserverManz> weak_self = shared_from_this();
    m_poller->async([args, weak_self]() {
        if (args.isMember("app")) {
            string _sapp = args["app"].asString();
            string _sstream = args["stream"].asString();
            auto strong_self = weak_self.lock();
            if (strong_self) {
                string _sUrl = strong_self->GetUrlByKey(_sapp, _sstream);
                if (!_sUrl.empty()) {
                    if (strong_self->OnaddStreamProxy(_sapp, _sstream, _sUrl)) {
                        InfoL << "拉流成功" << _sapp << ":" << _sstream;
                    }
                } else {
                    WarnL << "未找到拉流地址" << _sapp << ":" << _sstream;
                }
            }
        }
    });
    rval["code"] = 0;
    rval["msg"] = "success";
    return HTTP_SUCCESS_CODE;
}

int cserverManz::HandleAddPlayback(const Json::Value &args, Json::Value &rval) {
    int returnCode;
    try {
        // 根据 app和stream 判断流是否存在
        // 注册流
        if (args.isMember("app")) {
            string _sapp = args["app"].asString();
            string _sstream = args["stream"].asString();
            DebugL << "HandleAddPlayback" << _sapp << ":" << _sstream;
            string _sUrl = GetUrlByKey(_sapp, _sstream);
            if (!_sUrl.empty()) {
                if (OnaddStreamProxy(_sapp, _sstream, _sUrl)) {
                    InfoL << "Playback拉流成功" << _sapp << ":" << _sstream;
                    returnCode = HTTP_SUCCESS_CODE;

                } else {
                    WarnL << "Playback拉流失败" << _sapp << ":" << _sstream;
                    returnCode = HTTP_ERROR_CODE;
                }
            } else {
                WarnL << "Playback未找到拉流地址" << _sapp << ":" << _sstream;
                returnCode = HTTP_ERROR_CODE;
            }
        }

    } catch (const std::exception &e) {
        ErrorL << e.what();
        rval["code"] = -1;
        rval["msg"] = e.what();
        return HTTP_ERROR_CODE;
    }
    rval["code"] = returnCode;
    rval["msg"] = (returnCode == HTTP_SUCCESS_CODE) ? "success" : "failure";
    return returnCode;
}

bool cserverManz::OnInit() {
    m_mediaSecret = cjsonconfigz::Instance().getStringbyKey("mediaser.secret");
    m_mediaURL = cjsonconfigz::Instance().getStringbyKey("mediaser.ip");
    m_local_ip = cjsonconfigz::Instance().getStringbyKey("local.ip");
    InfoL << "MediaServer:" << m_mediaURL << ",IP:" << m_local_ip;
    OnInitAPIFUN();
    OnInitListener();
    return true;
}

void cserverManz::UnInit() {}

void cserverManz::OnStart() {
    // 判断是否开启测试
    int itest = cjsonconfigz::Instance().getIntbyKey("test.istest");
    if (itest == 1) {
        InfoL << "测试模式开启";
        string _sapp = "rst";
        string _sstream = "3b9bdd6bb05d1e7c30522048695db04c";
        //"rtsp://admin:pdf123456@192.168.0.64:554/Streaming/channels/501";
        string _sUrl = cjsonconfigz::Instance().getStringbyKey("test.url");
        InfoL << "测试拉流:" << _sUrl;
        OnaddStreamProxy(_sapp, _sstream, _sUrl);
        //
    }
}

// if (strstr(parser.Url().data(), "/index/") == parser.Url().data()) {
//     if (parser["Content-Type"].find("application/json") == string::npos) {
//         ErrorL << "该接口只支持json格式的请求";
//         sendErrorResponse("该接口只支持json格式的请求");
//         return;
//     }

//     // 参数解析成json对象然后处理
//     Json::Value args;

// weak_ptr<cserverManz> weak_self = shared_from_this();

// // 根据json内容查找到源然后注册源
// // app
// // stream
// // url
// m_poller->async([args, weak_self]() {
//     if (args.isMember("app")) {
//         DebugL << "args.isMember";
//         string _sapp = args["app"].asString();
//         string _sstream = args["stream"].asString();
//         // string _sUrl = "rtsp://admin:pdf123456@192.168.0.64:554/Streaming/channels/501";
//         auto strong_self = weak_self.lock();
//         if (strong_self) {
//             string _sUrl = strong_self->GetUrlByKey(_sapp, _sstream);
//             if (!_sUrl.empty()) {
//                 strong_self->OnaddStreamProxy(_sapp, _sstream, _sUrl);
//             }
//         }
//     }
// });
// Json::Value _val;
// _val["code"] = 0;
// _val["msg"] = "success";
//     sendResponse(200, _val);
// } else if (strstr(parser.Url().data(), "/api/") == parser.Url().data()) {
//     // 把信息保存起来
//     consumed = true; // 该http请求已被消费
//     // DebugL << parser.Content();
//     if (parser["Content-Type"].find("application/x-www-form-urlencoded") == 0) {
//         // ApiArgsType allArgs;
//         try {
//             Json::Value allArgs;
//             for (auto &pr : parser.getUrlArgs()) {
//                 allArgs[pr.first] = pr.second;
//             }
//         if (allArgs.isMember("app")) {
//             SetUrlByKey(allArgs["app"].asString(), allArgs["stream"].asString(), allArgs["url"].asString());
//         }
//     } catch (const std::exception &e) {
//         ErrorL << e.what();
//         sendErrorResponse(e.what());
//         return;
//     }
// }
// Json::Value _val;
// _val["code"] = 0;
// _val["msg"] = "success";
// _val["ip"] = m_local_ip;
//     sendResponse(200, _val);
// }

// 未知原因不能用
// bool cserverManz::OnaddStreamProxy(const string &app, const string &stream, const string sUrl) {
//     //
//     /index/api/addStreamProxy?secret={{ZLMediaKit_secret}}&vhost={{defaultVhost}}&app=live&stream=test&url=rtmp://live.hkstv.hk.lxdns.com/live/hks2&auto_close=

//     DebugL << "OnaddStreamProxy";
//     HttpRequester::Ptr requesterPost(new HttpRequester());
//     // 使用 POST 方式请求
//     requesterPost->setMethod("POST");
//     // 设置 POST 参数列表
//     HttpArgs args;
//     args["secret"] = m_mediaSecret;
//     args["vhost"] = "__defaultVhost__";
//     args["app"] = app;
//     args["stream"] = stream;
//     args["url"] = sUrl;
//     requesterPost->setBody(args.make());

//     DebugL << m_mediaURL;
//     DebugL << app;
//     DebugL << stream;
//     DebugL << m_mediaSecret;
//     string _tURL = str_format("%s%s", m_mediaURL.c_str(), "/index/api/addStreamProxy/");
//     DebugL << _tURL;
//     // 开启请求
//     requesterPost->startRequester(_tURL, [](const SockException &ex, const Parser &parser) {
//         DebugL << "111111111111 ===================== addStreamProxy ==========================";
//         if (ex) {
//             // 网络相关的错误
//             WarnL << "network err:" << ex.getErrCode() << " " << ex.what();
//         } else {
//             // 打印http回复信息
//             _StrPrinter printer;
//             for (auto &pr : parser.getHeader()) {
//                 printer << pr.first << ":" << pr.second << "\r\n";
//             }
//             InfoL << "status:" << parser.Url() << "\r\n"
//                   << "header:\r\n"
//                   << (printer << endl) << "\r\nbody:" << parser.Content();
//         }
//     });
//     DebugL << "End..............";
// }